import { create } from 'zustand';
import { persist, PersistStorage, StorageValue, redux } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';

export const SETTINGSKEY = 'WPCARU';
export const settingsStorage = storage.defineItem<StorageValue<State>>(`local:${SETTINGSKEY}`);

export enum Status {
  STOP,
  RUNNING,
}

export enum EditorButton {
  LEFT = 'left',
  RIGHT = 'right',
}

export enum PersistenMode {
  FlickerFreeMode = 'filicker-free',
  RollPollingMode = 'roll-polling',
  GlobalMode = 'global',
}

export type EditorSettings = {
  ctrl: boolean;
  alt: boolean;
  shift: boolean;
  button: EditorButton;
};

export type PersistentSettings = {
  needPersistent: boolean;
  currentMode: PersistenMode;
  flickerFree: {
    duration: number;
  };
  rollPolling: {
    interval: number;
    duration: number;
  };
};

export const defaultState: State = {
  status: Status.RUNNING,
  editorSettings: {
    ctrl: true,
    alt: true,
    shift: false,
    button: EditorButton.RIGHT,
  },
  persistentSettings: {
    needPersistent: true,
    currentMode: PersistenMode.FlickerFreeMode,
    flickerFree: {
      duration: 5000,
    },
    rollPolling: {
      interval: 30,
      duration: 5000,
    },
  },
};

export interface State {
  status: Status;
  editorSettings: EditorSettings;
  persistentSettings: PersistentSettings;
}

type Actions =
  | {
      type: 'reset';
    }
  | ({
      type: 'update';
    } & {
      [P in keyof State]?: State[P];
    });

const persistStorage: PersistStorage<State> = {
  getItem: async () => {
    const state = await settingsStorage.getValue();
    if (!state) {
      return {
        state: defaultState,
        version: 0,
      };
    }
    return state;
  },
  setItem: (key, newValue): void => {
    settingsStorage.setValue(newValue);
    // 每一次改动都要同步一份数据到本地存储,以便在第一时间可以进行替换监听
    saveLocal(newValue.state);
  },
  removeItem: (): void => {
    settingsStorage.removeValue();
  },
};

const reducer = (state: State, { type, ...props }: Actions) => {
  switch (type) {
    case 'reset':
      return defaultState;
    case 'update':
      return {
        ...state,
        ...props,
      };
  }
};

export const useSettingsStore = create(
  persist(immer(redux<State, Actions>(reducer, defaultState)), {
    name: SETTINGSKEY,
    storage: persistStorage,
  }),
);

settingsStorage.watch((newValue) => {
  if (newValue) {
    useSettingsStore.dispatch({
      type: 'update',
      ...newValue.state,
    });
  }
});

// 读取一份配置到当前页面的本地存储,以便在替换时可以同步获取配置
function saveLocal(data: State) {
  if (localStorage) {
    localStorage.setItem(SETTINGSKEY, JSON.stringify(data));
  }
}
// 对于新页面需要及时更新值,不然本地缓存是没有对应的数据的
settingsStorage.getValue().then((value) => {
  if (value) {
    saveLocal(value?.state);
  }
});
